﻿using System.Collections.Generic;
using System.Threading;

namespace Td.Additional.Collections
{
    /// <summary>
    /// Syncronized queue.
    /// See also: http://www.mycsharp.de/wbb2/thread.php?threadid=80713.
    /// </summary>
    /// <typeparam name="T">Type of queued items.</typeparam>
    public class SyncQueue<T>
    {
        #region Private fields

        private Queue<T> _q = new Queue<T>();

        #endregion

        #region Queue methods

        /// <summary>
        /// Enqueues the specified item.
        /// </summary>
        /// <param name="tItem">The item.</param>
        public void Enqueue(T tItem)
        {
            lock (this)
            {
                _q.Enqueue(tItem);
                Monitor.Pulse(this);
                System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.Name + " Enqueue ==> " + _q.Count);
            }
        }

        /// <summary>
        /// Dequeues the next item. If no item in queue, method waits, until an item is in the queue.
        /// </summary>
        /// <returns></returns>
        public T Dequeue()
        {
            Monitor.Enter(this);
            try
            {
                while (_q.Count == 0)
                {
                    System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.Name + " Wait");
                    Monitor.Wait(this);
                }
                System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.Name + " Dequeue ==> " + (_q.Count - 1));
                return _q.Dequeue();
            }
            finally
            {
                Monitor.Exit(this);
            }
        }

        #endregion
    }
}